home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / tools / anwender / astrolog / sources / xscreen.c < prev   
C/C++ Source or Header  |  1995-11-25  |  52KB  |  1,762 lines

  1. /*
  2. ** Astrolog (Version 4.40) File: xscreen.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (astara@u.washington.edu). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 1/29/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38. #ifdef ATARI                /* Ajout Abel PHILIPPE */
  39. #include <screen.h>
  40. void BGIDriver(void);
  41. #endif
  42.  
  43. #ifdef GRAPH
  44. /*
  45. ******************************************************************************
  46. ** Astrolog Icon.
  47. ******************************************************************************
  48. */
  49.  
  50. #ifdef X11
  51. /* This information used to define Astrolog's X icon (Rainbow over Third */
  52. /* Eye) is identical to the output format used by the bitmap program.    */
  53. /* You could extract this section and run xsetroot -bitmap on it.        */
  54.  
  55. #define icon_width 63
  56. #define icon_height 32
  57. static char icon_bits[] = {
  58.  0x00,0x00,0x00,0xa8,0x0a,0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x55,0x01,0x00,
  59.  0x00,0x00,0x00,0xa8,0xaa,0xaa,0x0a,0x00,0x00,0x00,0x00,0x54,0xf5,0x57,0x15,
  60.  0x00,0x00,0x00,0x80,0xaa,0xaa,0xaa,0xaa,0x00,0x00,0x00,0x40,0xd5,0xff,0xff,
  61.  0x55,0x01,0x00,0x00,0xa0,0xaa,0xaa,0xaa,0xaa,0x02,0x00,0x00,0x50,0xfd,0xff,
  62.  0xff,0x5f,0x05,0x00,0x00,0xa8,0xaa,0x2a,0xaa,0xaa,0x0a,0x00,0x00,0xd4,0xff,
  63.  0xaf,0xfa,0xff,0x15,0x00,0x00,0xaa,0x2a,0x00,0x00,0xaa,0x2a,0x00,0x00,0xf5,
  64.  0xbf,0xaa,0xaa,0xfe,0x57,0x00,0x80,0xaa,0x02,0x00,0x00,0xa0,0xaa,0x00,0x40,
  65.  0xfd,0xab,0xfa,0xaf,0xea,0x5f,0x01,0xa0,0xaa,0x80,0xff,0xff,0x80,0xaa,0x02,
  66.  0x50,0xff,0xea,0xff,0xff,0xab,0x7f,0x05,0xa0,0x2a,0xf0,0xff,0xff,0x07,0xaa,
  67.  0x02,0xd0,0xbf,0xfa,0x0f,0xf8,0xaf,0x7e,0x05,0xa8,0x0a,0xfc,0x01,0xc0,0x1f,
  68.  0xa8,0x0a,0xd4,0xaf,0x7e,0x00,0x00,0xbf,0xfa,0x15,0xa8,0x0a,0x3f,0x00,0x00,
  69.  0x7e,0xa8,0x0a,0xf4,0xaf,0x1f,0xe0,0x03,0xfc,0xfa,0x15,0xaa,0x82,0x0f,0xdc,
  70.  0x1d,0xf8,0xa0,0x2a,0xf4,0xab,0x07,0x23,0x62,0xf0,0xea,0x17,0xaa,0xc2,0x87,
  71.  0x91,0xc4,0xf0,0xa1,0x2a,0xf4,0xeb,0xc3,0xd0,0x85,0xe1,0xeb,0x17,0xaa,0xe0,
  72.  0x83,0x91,0xc4,0xe0,0x83,0x2a,0xf5,0xeb,0x03,0x23,0x62,0xe0,0xeb,0x57,0xaa,
  73.  0xe0,0x01,0xdc,0x1d,0xc0,0x83,0x2a,0xf5,0xeb,0x01,0xe0,0x03,0xc0,0xeb,0x57,
  74.  0xaa,0xe0,0x01,0x00,0x00,0xc0,0x83,0x2a,0xfd,0xeb,0x01,0x00,0x00,0xc0,0xeb,
  75.  0x5f};
  76. #endif
  77.  
  78.  
  79. /*
  80. ******************************************************************************
  81. ** Interactive Screen Graphics Routines.
  82. ******************************************************************************
  83. */
  84.  
  85. /* Set up all the colors used by the program, i.e. the foreground and   */
  86. /* background colors, and all the colors in the object arrays, based on */
  87. /* whether or not we are in monochrome and/or reverse video mode.       */
  88.  
  89. void InitColorsX()
  90. {
  91.   int i;
  92. #ifdef X11
  93.   Colormap cmap;
  94.   XColor xcol;
  95.  
  96.   if (!gi.fFile) {
  97.     cmap = XDefaultColormap(gi.disp, gi.screen);
  98.  
  99.     /* Allocate a color from the present X11 colormap. Given a string like */
  100.     /* "violet", allocate this color and return a value specifying it.     */
  101.  
  102.     for (i = 0; i < 16; i++) {
  103.       XParseColor(gi.disp, cmap, szColorX[i], &xcol);
  104.       XAllocColor(gi.disp, cmap, &xcol);
  105.       rgbind[i] = xcol.pixel;
  106.     }
  107.   }
  108. #endif
  109.   gi.kiOn   = kMainA[!gs.fInverse];
  110.   gi.kiOff  = kMainA[gs.fInverse];
  111.   gi.kiLite = gs.fColor ? kMainA[2+gs.fInverse] : gi.kiOn;
  112.   gi.kiGray = gs.fColor ? kMainA[3-gs.fInverse] : gi.kiOn;
  113.   for (i = 0; i <= 8; i++)
  114.     kMainB[i]    = gs.fColor ? kMainA[i]    : gi.kiOn;
  115.   for (i = 0; i <= 7; i++)
  116.     kRainbowB[i] = gs.fColor ? kRainbowA[i] : gi.kiOn;
  117.   for (i = 0; i < 4; i++)
  118.     kElemB[i]    = gs.fColor ? kElemA[i]    : gi.kiOn;
  119.   for (i = 0; i <= cAspect; i++)
  120.     kAspB[i]     = gs.fColor ? kAspA[i]     : gi.kiOn;
  121.   for (i = 0; i <= cObj; i++)
  122.     kObjB[i]     = gs.fColor ? kObjA[i]     : gi.kiOn;
  123. #ifdef X11
  124.   if (!gi.fFile) {
  125.     XSetBackground(gi.disp, gi.gc,   rgbind[gi.kiOff]);
  126.     XSetForeground(gi.disp, gi.pmgc, rgbind[gi.kiOff]);
  127.   }
  128. #endif
  129. }
  130.  
  131.  
  132. #ifdef ISG
  133. /* This routine opens up and initializes a window and prepares it to be */
  134. /* drawn upon, and gets various information about the display, too.     */
  135.  
  136. void BeginX()
  137. {
  138. #ifdef X11
  139.   gi.disp = XOpenDisplay(gs.szDisplay);
  140.   if (gi.disp == NULL) {
  141.     PrintError("Can't open display.");
  142.     Terminate(tcFatal);
  143.   }
  144.   gi.screen = DefaultScreen(gi.disp);
  145.   bg = BlackPixel(gi.disp, gi.screen);
  146.   fg = WhitePixel(gi.disp, gi.screen);
  147.   hint.x = gi.xOffset; hint.y = gi.yOffset;
  148.   hint.width = gs.xWin; hint.height = gs.yWin;
  149.   hint.min_width = BITMAPX1; hint.min_height = BITMAPY1;
  150.   hint.max_width = BITMAPX;  hint.max_height = BITMAPY;
  151.   hint.flags = PPosition | PSize | PMaxSize | PMinSize;
  152. #if FALSE
  153.   wmhint = XGetWMHints(gi.disp, gi.wind);
  154.   wmhint->input = True;
  155.   XSetWMHints(gi.disp, gi.wind, wmhint);
  156. #endif
  157.   gi.depth = DefaultDepth(gi.disp, gi.screen);
  158.   if (gi.depth < 5) {
  159.     gi.fMono = fTrue;      /* Is this a monochrome monitor? */
  160.     gs.fColor = fFalse;
  161.   }
  162.   gi.root = RootWindow(gi.disp, gi.screen);
  163.   if (gs.fRoot)
  164.     gi.wind = gi.root;     /* If -XB in effect, we'll use the root window. */
  165.   else
  166.     gi.wind = XCreateSimpleWindow(gi.disp, DefaultRootWindow(gi.disp),
  167.       hint.x, hint.y, hint.width, hint.height, 5, fg, bg);
  168.   gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  169.   gi.icon = XCreateBitmapFromData(gi.disp, DefaultRootWindow(gi.disp),
  170.     icon_bits, icon_width, icon_height);
  171.   if (!gs.fRoot)
  172.     XSetStandardProperties(gi.disp, gi.wind, szAppName, szAppName, gi.icon,
  173.       (char **)xkey, 0, &hint);
  174.  
  175.   /* We have two graphics workareas. One is what the user currently sees in */
  176.   /* the window, and the other is what we are currently drawing on. When    */
  177.   /* done, we can quickly copy this to the viewport for a smooth look.      */
  178.  
  179.   gi.gc = XCreateGC(gi.disp, gi.wind, 0, 0);
  180.   XSetGraphicsExposures(gi.disp, gi.gc, 0);
  181.   gi.pmgc = XCreateGC(gi.disp, gi.wind, 0, 0);
  182.   InitColorsX();                           /* Go set up colors. */
  183.   if (!gs.fRoot)
  184.     XSelectInput(gi.disp, gi.wind, KeyPressMask | StructureNotifyMask |
  185.       ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
  186.   XMapRaised(gi.disp, gi.wind);
  187.   XSync(gi.disp, 0);
  188.   XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  189. #endif /* X11 */
  190.  
  191. #ifdef MSG
  192.   if (!FValidResmode(gi.nRes))    /* Initialize graphics mode to hi-res. */
  193.     gi.nRes = gs.nResHi;
  194.   _setvideomode(gi.nRes);
  195.   if (_grstatus()) {
  196.     PrintError("Can't enter graphics mode.");
  197.     Terminate(tcFatal);
  198.   }
  199.   _getvideoconfig((struct videoconfig far *) &gi.cfg);
  200.   if (gi.cfg.numcolors < 16) {
  201.     gi.fMono  = fTrue;
  202.     gs.fColor = fFalse;
  203.   }
  204.   _remapallpalette((long FAR *) rgb);
  205.   _setactivepage(0);
  206.   _setvisualpage(0);
  207.   InitColorsX();
  208. #ifdef MOUSE
  209.   MouseInit(xPcScreen, yPcScreen);
  210. #endif
  211.   /* Make sure we reset textrows upon restart. */
  212.   gs.nTextRows = abs(gs.nTextRows);
  213. #endif /* MSG */
  214.  
  215. #ifdef BGI
  216.   int i;
  217.   static struct palettetype pal;
  218.  
  219.   if (!FValidResmode(gi.nRes))    /* Initialize graphics mode to hi-res. */
  220.     gi.nRes = gs.nResHi;
  221.   if (!gi.fLoaded) {
  222. #ifdef ATARI
  223.     registerbgidriver(BGIDriver);
  224. #else                                        /* Ajout Abel PHILIPPE */
  225.     registerfarbgidriver(ATT_driver_far);      /* attf.obj     */
  226.     registerfarbgidriver(CGA_driver_far);      /* cgaf.obj     */
  227.     registerfarbgidriver(EGAVGA_driver_far);   /* egavgaf.obj  */
  228.     registerfarbgidriver(Herc_driver_far);     /* hercf.obj    */
  229.     registerfarbgidriver(IBM8514_driver_far);  /* ibm8514f.obj */
  230.     registerfarbgidriver(PC3270_driver_far);   /* pc3270f.obj  */
  231. #endif                            /* Ajout Abel PHILIPPE */
  232.     gi.nDriver = DETECT;
  233.     initgraph(&gi.nDriver, &gi.nGraph, "");
  234.     gi.fLoaded = fTrue;
  235.   }
  236.   if (gi.nRes <= 0) {
  237.     switch (gi.nDriver) {
  238.     case CGA:      gi.nGraph = CGAHI;      break;
  239.     case MCGA:     gi.nGraph = MCGAHI;     break;
  240.     case EGA:      gi.nGraph = EGAHI;      break;
  241.     case EGA64:    gi.nGraph = EGA64HI;    break;
  242.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  243.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  244.     case ATT400:   gi.nGraph = ATT400HI;   break;
  245.     case VGA:      gi.nGraph = VGAHI;      break;
  246.     case PC3270:   gi.nGraph = PC3270HI;   break;
  247.     case IBM8514:  gi.nGraph = IBM8514HI;  break;
  248.     default:       gi.nGraph = 0;
  249.     }
  250.   } else {
  251.     switch (gi.nDriver) {
  252.     case CGA:      gi.nGraph = CGAHI;      break;
  253.     case MCGA:     gi.nGraph = MCGAHI;     break;
  254.     case EGA:      gi.nGraph = EGAHI;      break;
  255.     case EGA64:    gi.nGraph = EGA64HI;    break;
  256.     case EGAMONO:  gi.nGraph = EGAMONOHI;  break;
  257.     case HERCMONO: gi.nGraph = HERCMONOHI; break;
  258.     case ATT400:   gi.nGraph = ATT400HI;   break;
  259.     case VGA:      gi.nGraph = VGAMED;     break;
  260.     case PC3270:   gi.nGraph = PC3270HI;   break;
  261.     case IBM8514:  gi.nGraph = IBM8514LO;  break;
  262.     default:       gi.nGraph = 0;
  263.     }
  264.   }
  265. #ifdef ATARI                                /* Ajout Abel PHILIPPE */
  266.   Cur_off();
  267. #endif
  268.   setgraphmode(gi.nGraph);
  269.   if (graphresult()) {
  270.     PrintError("Can't enter graphics mode.");
  271.     Terminate(tcFatal);
  272.   }
  273.   gi.nPages = 1 + (gi.nDriver == HERCMONO ||
  274.     (gi.nDriver == VGA && gi.nGraph != VGAHI) || gi.nDriver == EGA);
  275.   if (getmaxcolor()+1 < 16) {
  276.     gi.fMono  = fTrue;
  277.     gs.fColor = fFalse;
  278.   }
  279.   getpalette(&pal);
  280.   for (i = 0; i < pal.size; i++)
  281.     pal.colors[i] = (char)rgb[i];
  282.   setallpalette(&pal);
  283.   setactivepage(0);
  284.   setvisualpage(0);
  285.   gi.nPageCur = 0;
  286.   InitColorsX();
  287. #ifdef MOUSE
  288.   MouseInit(xPcScreen, yPcScreen);
  289. #endif
  290.   /* Make sure we reset textrows upon restart. */
  291.   gs.nTextRows = abs(gs.nTextRows);
  292. #endif /* BGI */
  293. }
  294.  
  295.  
  296. /* Add a certain amount of time to the current hour/day/month/year quantity */
  297. /* defining the present chart. This is used by the chart animation feature. */
  298. /* We can add or subtract anywhere from 1 to 9 seconds, minutes, hours,     */
  299. /* days, months, years, decades, centuries, or millenia in any one call.    */
  300. /* This is mainly just addition to the appropriate quantity, but we have    */
  301. /* to check for overflows, e.g. Dec 30 + 3 days = Jan 2 of Current year + 1 */
  302.  
  303. void AddTime(mode, toadd)
  304. int mode, toadd;
  305. {
  306.   int d;
  307.   real h, m;
  308.  
  309.   if (!FBetween(mode, 1, 9))
  310.     mode = 4;
  311.  
  312.   h = RFloor(TT);
  313.   m = RFract(TT)*100.0;
  314.   if (mode == 1)
  315.     m += 1.0/60.0*(real)toadd;    /* Add seconds. */
  316.   else if (mode == 2)
  317.     m += (real)toadd;             /* add minutes. */
  318.  
  319.   /* Add hours, either naturally or if minute value overflowed. */
  320.  
  321.   if (m < 0.0 || m >= 60.0 || mode == 3) {
  322.     if (m >= 60.0) {
  323.       m -= 60.0; toadd = NSgn(toadd);
  324.     } else if (m < 0.0) {
  325.       m += 60.0; toadd = NSgn(toadd);
  326.     }
  327.     h += (real)toadd;
  328.   }
  329.  
  330.   /* Add days, either naturally or if hour value overflowed. */
  331.  
  332.   if (h >= 24.0 || h < 0.0 || mode == 4) {
  333.     if (h >= 24.0) {
  334.       h -= 24.0; toadd = NSgn(toadd);
  335.     } else if (h < 0.0) {
  336.       h += 24.0; toadd = NSgn(toadd);
  337.     }
  338.     DD = AddDay(MM, DD, YY, toadd);
  339.   }
  340.  
  341.   /* Add months, either naturally or if day value overflowed. */
  342.  
  343.   if (DD > (d = DayInMonth(MM, YY)) || DD < 1 || mode == 5) {
  344.     if (DD > d) {
  345.       DD -= d; toadd = NSgn(toadd);
  346.     } else if (DD < 1) {
  347.       DD += DayInMonth(Mod12(MM - 1), YY);
  348.       toadd = NSgn(toadd);
  349.     }
  350.     MM += toadd;
  351.   }
  352.  
  353.   /* Add years, either naturally or if month value overflowed. */
  354.  
  355.   if (MM > 12 || MM < 1 || mode == 6) {
  356.     if (MM > 12) {
  357.       MM -= 12; toadd = NSgn(toadd);
  358.     } else if (MM < 1) {
  359.       MM += 12; toadd = NSgn(toadd);
  360.     }
  361.     YY += toadd;
  362.   }
  363.   if (mode == 7)
  364.     YY += 10 * toadd;      /* Add decades.   */
  365.   else if (mode == 8)
  366.     YY += 100 * toadd;     /* Add centuries. */
  367.   else if (mode == 9)
  368.     YY += 1000 * toadd;    /* Add millenia.  */
  369.   TT = h+m/100.0;          /* Recalibrate hour time. */
  370. }
  371.  
  372.  
  373. /* Animate the current chart based on the given values indicating how much  */
  374. /* to update by. We update and recast the current chart info appropriately. */
  375.  
  376. void Animate(mode, toadd)
  377. int mode, toadd;
  378. {
  379.   if (gi.nMode == gWorldMap || gi.nMode == gGlobe || gi.nMode == gPolar) {
  380.     gs.nRot += toadd;
  381.     if (gs.nRot >= nDegMax)     /* For animating globe display, add */
  382.       gs.nRot -= nDegMax;       /* in appropriate degree value.     */
  383.     else if (gs.nRot < 0)
  384.       gs.nRot += nDegMax;
  385.   } else {
  386.     if (mode == 10) {
  387. #ifdef TIME
  388.       /* For the continuous chart update to present moment */
  389.       /* animation mode, go get whatever time it is now.   */
  390.       FInputData(szNowCore);
  391. #else
  392.       ciCore = ciMain;
  393.       AddTime(1, toadd);
  394. #endif
  395.     } else {  /* Otherwise add on appropriate time vector to chart info. */
  396.       ciCore = ciMain;
  397.       AddTime(mode, toadd);
  398.     }
  399.     ciMain = ciCore;
  400.     if (us.nRel)
  401.       CastRelation(fFalse);
  402.     else
  403.       CastChart(fTrue);
  404.   }
  405. }
  406.  
  407.  
  408. /* This routine exits graphics mode, prompts the user for a set of command */
  409. /* switches, processes them, and returns to the previous graphics with the */
  410. /* new settings in effect, allowing one to change most any setting without */
  411. /* having to lose their graphics state or fall way back to a -Q loop.      */
  412.  
  413. void CommandLineX()
  414. {
  415.   char szCommandLine[cchSzMax], *rgsz[MAXSWITCHES];
  416.   int argc, fT, fPause = fFalse;
  417.  
  418.   ciCore = ciMain;
  419. #ifdef MSG
  420.   _setvideomode(_DEFAULTMODE);
  421.   _settextrows(gs.nTextRows);
  422. #endif
  423. #ifdef BGI
  424.   restorecrtmode();
  425. #ifdef ATARI                    /* Ajout Abel PHILIPPE */
  426.   Cur_on();
  427. #else
  428.   if (gs.nTextRows > 25)
  429.     textmode(C4350);
  430. #endif                            /* Ajout Abel PHILIPPE */
  431. #endif
  432.   fT = us.fLoop; us.fLoop = fTrue;
  433.   argc = NPromptSwitches(szCommandLine, rgsz);
  434.   is.cchRow = 0;
  435.   is.fSzInteract = fTrue;
  436.   if (!FProcessSwitches(argc, rgsz))
  437.     fPause = fTrue;
  438.   else {
  439.     is.fMult = fFalse;
  440.     FPrintTables();
  441.     if (is.fMult) {
  442.       ClearB((lpbyte)&us.fCredit,
  443.         (int)((lpbyte)&us.fLoop - (lpbyte)&us.fCredit));
  444.       fPause = fTrue;
  445.     }
  446.   }
  447.  
  448. #ifdef PCG
  449.   /* Pause for the user if there was either an error processing the    */
  450.   /* switches, or one of the informational text tables was brought up. */
  451.  
  452.   if (fPause) {
  453.     AnsiColor(kDefault);
  454.     is.cchRow = 0;
  455.     PrintSz("Press any key to return to graphics.\n");
  456.     while (!kbhit())
  457.       ;
  458.     getch();
  459.   }
  460. #endif
  461.   is.fSzInteract = fFalse;
  462.   us.fLoop = fT;
  463.   ciMain = ciCore;
  464.   BeginX();
  465. }
  466.  
  467.  
  468. /* Given two chart size values, adjust them such that the chart will look */
  469. /* "square". We round the higher value down and check certain conditions. */
  470.  
  471. void SquareX(x, y, force)
  472. int *x, *y, force;
  473. {
  474.   if (!force && !fSquare)    /* Unless we want to force a square, realize */
  475.     return;                  /* that some charts look better rectangular. */
  476.   if (*x > *y)
  477.     *x = *y;
  478.   else
  479.     *y = *x;
  480. #ifdef PCG
  481.   if (FEgaRes(gi.nRes))         /* Scale horizontal size if we're in a PC */
  482.     *x = VgaFromEga(*x);        /* graphics mode without "square" pixels. */
  483.   else if (FCgaRes(gi.nRes))
  484.     *x = VgaFromCga(*x);
  485. #endif
  486.   if (fSidebar)      /* Take into account chart's sidebar, if any. */
  487.     *x += xSideT;
  488. }
  489.  
  490.  
  491. /* This routine gets called after graphics are brought up and displayed     */
  492. /* on the screen. It loops, processing key presses, mouse clicks, etc, that */
  493. /* the window receives, until the user specifies they want to exit program. */
  494.  
  495. void InteractX()
  496. {
  497. #ifdef X11
  498.   char sz[cchSzDef];
  499.   XEvent xevent;
  500.   KeySym keysym;
  501.   int fResize = fFalse, fRedraw = fTrue;
  502. #else /* PCG */
  503. #ifdef MOUSE
  504.   int eventx, eventy, eventbtn;
  505. #endif
  506.   int fResize = fTrue, fRedraw = fFalse;
  507. #endif /* PCG */
  508.   int fBreak = fFalse, fPause = fFalse, fCast = fFalse, xcorner = 7,
  509. #ifdef MOUSE
  510.     mousex = -1, mousey = -1, buttonx = -1, buttony = -1,
  511. #endif
  512.     dir = 1, length, key, i;
  513.   bool fT;
  514. #ifdef MOUSE
  515.   KI coldrw = gi.kiLite;
  516. #endif
  517.  
  518.   neg(gs.nAnim);
  519.   while (!fBreak) {
  520.     gi.nScale = gs.nScale/100;
  521.  
  522.     /* Some chart windows, like the world maps and aspect grids, should */
  523.     /* always be a certian size, so correct if a resize was attempted.  */
  524.  
  525.     if (fMap) {
  526.       length = nDegMax*gi.nScale;
  527.       if (gs.xWin != length) {
  528.         gs.xWin = length;
  529.         fResize = fTrue;
  530.       }
  531.       length = nDegHalf*gi.nScale;
  532.       if (gs.yWin != length) {
  533.         gs.yWin = length;
  534.         fResize = fTrue;
  535.       }
  536.     } else if (gi.nMode == gGrid) {
  537.       if (gs.xWin != (length =
  538.         (gs.nGridCell + (us.nRel <= rcDual))*CELLSIZE*gi.nScale+1)) {
  539.         gs.xWin = length;
  540.         fResize = fTrue;
  541.       } if (gs.yWin != length) {
  542.         gs.yWin = length;
  543.         fResize = fTrue;
  544.       }
  545.  
  546.     /* Make sure the window isn't too large or too small. */
  547.  
  548.     } else {
  549.       if (gs.xWin < BITMAPX1) {
  550.         gs.xWin = BITMAPX1;
  551.         fResize = fTrue;
  552.       } else if (gs.xWin > BITMAPX) {
  553.         gs.xWin = BITMAPX;
  554.         fResize = fTrue;
  555.       }
  556.       if (gs.yWin < BITMAPY1) {
  557.         gs.yWin = BITMAPY1;
  558.         fResize = fTrue;
  559.       } else if (gs.yWin > BITMAPY) {
  560.         gs.yWin = BITMAPY;
  561.         fResize = fTrue;
  562.       }
  563.     }
  564.  
  565.     /* If in animation mode, ensure we are in the flicker free resolution. */
  566.  
  567.     if (gs.nAnim < 0) {
  568.       neg(gs.nAnim);
  569. #ifdef PCG
  570.       if (gi.nRes == gs.nResHi && !gs.fJetTrail) {
  571.         gi.nRes = gs.nResLo;
  572.         BeginX();
  573.         gs.xWin = xPcScreen;
  574.         gs.yWin = yPcScreen;
  575.         SquareX(&gs.xWin, &gs.yWin, fFalse);
  576.         fResize = fTrue;
  577.       }
  578. #endif
  579.     }
  580.  
  581.     /* Physically resize window if we've changed the size parameters. */
  582.  
  583.     if (fResize) {
  584.       fResize = fFalse;
  585. #ifdef X11
  586.       XResizeWindow(gi.disp, gi.wind, gs.xWin, gs.yWin);
  587.       XFreePixmap(gi.disp, gi.pmap);
  588.       gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  589. #else
  590.       if (xPcScreen > gs.xWin)
  591.         gi.xOffset = (xPcScreen - gs.xWin) / 2;
  592.       else {
  593.         if (xcorner % 3 == 1)
  594.           gi.xOffset = 0;
  595.         else if (xcorner % 3 == 0)
  596.           gi.xOffset = -gs.xWin + xPcScreen;
  597.         else
  598.           gi.xOffset = -(gs.xWin - xPcScreen) / 2;
  599.       }
  600.       if (yPcScreen > gs.yWin)
  601.         gi.yOffset = (yPcScreen - gs.yWin) / 2;
  602.       else {
  603.         if (xcorner > 6)
  604.           gi.yOffset = 0;
  605.         else if (xcorner < 4)
  606.           gi.yOffset = -gs.yWin + yPcScreen;
  607.         else
  608.           gi.yOffset = -(gs.yWin - yPcScreen) / 2;
  609.       }
  610. #endif
  611.       fRedraw = fTrue;
  612.     }
  613.  
  614.     /* Recast chart if the chart information has changed any. */
  615.  
  616.     if (fCast) {
  617.       fCast = fFalse;
  618.       ciCore = ciMain;
  619.       if (us.nRel)
  620.         CastRelation(fFalse);
  621.       else
  622.         CastChart(fTrue);
  623.       fRedraw = fTrue;
  624.     }
  625.     if (gs.nAnim && !fPause)
  626.       fRedraw = fTrue;
  627.  
  628.     /* Update the screen if anything has changed since last time around. */
  629.  
  630.     if (fRedraw) {
  631.       fRedraw = fFalse;
  632.  
  633.       /* If we're in animation mode, change the chart info appropriately. */
  634.  
  635.       if (gs.nAnim && !fPause)
  636.         Animate(gs.nAnim, dir);
  637.  
  638.       /* Clear the screen and set up a buffer to draw in. */
  639.  
  640. #ifdef X11
  641.       XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  642. #else /* PCG */
  643. #ifdef MOUSE
  644.       MouseShow(fFalse);
  645. #endif
  646. #ifdef MSG
  647.       if (gi.cfg.numvideopages > 1)
  648.         _setactivepage(_getactivepage() == gs.fJetTrail);
  649. #else
  650.       if (gi.nPages > 1) {
  651.         gi.nPageCur = (gi.nPageCur == gs.fJetTrail);
  652.         setactivepage(gi.nPageCur);
  653.       }
  654. #endif
  655. #endif /* PCG */
  656.  
  657.       DrawChartX();
  658.  
  659.       /* Make the drawn chart visible in the current screen buffer. */
  660.  
  661. #ifdef X11
  662.       XSync(gi.disp, 0);
  663.       XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  664.         0, 0, gs.xWin, gs.yWin, 0, 0);
  665. #else /* PCG */
  666. #ifdef MSG
  667.       if (gi.cfg.numvideopages > 1)
  668.         _setvisualpage(_getactivepage());
  669. #else
  670.       if (gi.nPages > 1)
  671.         setvisualpage(gi.nPageCur);
  672. #endif
  673. #ifdef MOUSE
  674.       if (!gs.nAnim || fPause)
  675.         MouseShow(fTrue);
  676. #endif
  677. #endif /* PCG */
  678.     }  /* if */
  679.  
  680.     /* Now process what's on the event queue, i.e. any keys pressed, etc. */
  681.  
  682. #ifdef X11
  683.     if (XEventsQueued(gi.disp, QueuedAfterFlush /*QueuedAfterReading*/) ||
  684.       !gs.nAnim || fPause) {
  685.       XNextEvent(gi.disp, &xevent);
  686.  
  687.       /* Restore what's on window if a part of it gets uncovered. */
  688.  
  689.       if (xevent.type == Expose && xevent.xexpose.count == 0) {
  690.         XSync(gi.disp, 0);
  691.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  692.           0, 0, gs.xWin, gs.yWin, 0, 0);
  693.       }
  694.       switch (xevent.type) {
  695.  
  696.       /* Check for a manual resize of window by user. */
  697.  
  698.       case ConfigureNotify:
  699.         gs.xWin = xevent.xconfigure.width;
  700.         gs.yWin = xevent.xconfigure.height;
  701.         XFreePixmap(gi.disp, gi.pmap);
  702.         gi.pmap = XCreatePixmap(gi.disp, gi.wind, gs.xWin, gs.yWin, gi.depth);
  703.         fRedraw = fTrue;
  704.         break;
  705.       case MappingNotify:
  706.         XRefreshKeyboardMapping((XMappingEvent *)&xevent);
  707.         break;
  708.  
  709. #ifdef MOUSE
  710.       /* Process any mouse buttons the user pressed. */
  711.  
  712.       case ButtonPress:
  713.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  714.         if (xevent.xbutton.button == Button1) {
  715.           DrawColor(gi.kiLite);
  716.           DrawPoint(mousex, mousey);
  717.           XSync(gi.disp, 0);
  718.           XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  719.             0, 0, gs.xWin, gs.yWin, 0, 0);
  720.         } else if (xevent.xbutton.button == Button2 && (gi.nMode ==
  721.           gAstroGraph || gi.nMode == gWorldMap) && gs.nRot == 0) {
  722.           Lon = DegToDec(rDegHalf -
  723.             (real)(xevent.xbutton.x-1)/(real)(gs.xWin-2)*rDegMax);
  724.           Lat = DegToDec(rDegQuad -
  725.             (real)(xevent.xbutton.y-1)/(real)(gs.yWin-2)*181.0);
  726.           sprintf(sz, "Mouse is at %s.", SzLocation(Lon, Lat));
  727.           PrintNotice(sz);
  728.         } else if (xevent.xbutton.button == Button3)
  729.           fBreak = fTrue;
  730.         break;
  731.  
  732.       /* Check for user dragging any of the mouse buttons across window. */
  733.  
  734.       case MotionNotify:
  735.         DrawColor(coldrw);
  736.         DrawLine(mousex, mousey, xevent.xbutton.x, xevent.xbutton.y);
  737.         XSync(gi.disp, 0);
  738.         XCopyArea(gi.disp, gi.pmap, gi.wind, gi.gc,
  739.           0, 0, gs.xWin, gs.yWin, 0, 0);
  740.         mousex = xevent.xbutton.x; mousey = xevent.xbutton.y;
  741.         break;
  742. #endif
  743.  
  744.       /* Process any keys user pressed in window. */
  745.  
  746.       case KeyPress:
  747.         length = XLookupString((XKeyEvent *)&xevent, xkey, 10, &keysym, 0);
  748.         if (length == 1) {
  749.           key = xkey[0];
  750. #else /* PCG */
  751. #ifdef MOUSE
  752.       if ((!gs.nAnim || fPause) && MouseStatus(&eventx, &eventy, &eventbtn)) {
  753.  
  754.         /* If the left button is down, draw on the screen. */
  755.         if (eventbtn == mfLeft && mousex >= 0) {
  756.           MouseShow(fFalse);
  757.           DrawColor(coldrw);
  758.           PcMoveTo(mousex, mousey);
  759.           buttonx = eventx; buttony = eventy;
  760.           PcLineTo(buttonx, buttony);
  761.  
  762.         /* If the right button is down, change the default location. */
  763.         } else if (eventbtn == mfRight) {
  764.           if (fMap && gs.nRot == 0 && !gs.fConstel && !gs.fMollewide) {
  765.             Lon = rDegHalf-(real)(eventx-gi.xOffset)/(real)(gs.xWin-2)*rDegMax;
  766.             if (Lon < -rDegHalf)
  767.               Lon = -rDegHalf;
  768.             else if (Lon > rDegHalf)
  769.               Lon = rDegHalf;
  770.             Lat =  rDegQuad-(real)(eventy-gi.yOffset)/(real)(gs.yWin-2)*181.0;
  771.             if (Lat < -rDegQuad)
  772.               Lat = -rDegQuad;
  773.             else if (Lat > rDegQuad)
  774.               Lat = rDegQuad;
  775.             fCast = fTrue;
  776.  
  777.           /* Right button means draw lines if not in a world map mode. */
  778.           } else if (buttonx >= 0) {
  779.             MouseShow(fFalse);
  780.             DrawColor(coldrw);
  781.             PcMoveTo(buttonx, buttony);
  782.             PcLineTo(eventx, eventy);
  783.           }
  784.  
  785.         /* Middle button (which most PC's don't have) means exit program. */
  786.         } else if (eventbtn == mfMiddle)
  787.           fBreak = fTrue;
  788.  
  789.         mousex = eventx; mousey = eventy;
  790.         MouseShow(fTrue);
  791.       } else
  792. #endif /* MOUSE */
  793.         if (kbhit()) {
  794.           key = getch();
  795. #endif /* PCG */
  796. LSwitch:
  797.           switch (key) {
  798. #ifdef PCG
  799.           case chNull:
  800.             key = NFromAltN(getch());
  801.             goto LSwitch;
  802. #endif
  803.           case ' ':
  804.             fRedraw = fTrue;
  805.             break;
  806.           case 'p':
  807.             not(fPause);
  808.             break;
  809.           case 'r':
  810.             neg(dir);
  811.             break;
  812.           case 'x':
  813.             not(gs.fInverse);
  814.             InitColorsX();
  815.             fRedraw = fTrue;
  816.             break;
  817.           case 'm':
  818.             if (!gi.fMono) {
  819.               not(gs.fColor);
  820. #ifdef MSG
  821.               _getvideoconfig((struct videoconfig far *) &gi.cfg);
  822. #endif
  823.               InitColorsX();
  824.               fRedraw = fTrue;
  825.             }
  826.             break;
  827.           case 'B':
  828. #ifdef X11
  829.             XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  830.             XClearWindow(gi.disp, gi.root);
  831. #else
  832.             gs.xWin = xPcScreen;
  833.             gs.yWin = yPcScreen;
  834.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  835.             fResize = fTrue;
  836. #endif
  837.             break;
  838.           case 't':
  839.             not(gs.fText);
  840.             fRedraw = fTrue;
  841.             break;
  842.           case 'i':
  843.             not(gs.fAlt);
  844.             fRedraw = fTrue;
  845.             break;
  846.           case 'b':
  847.             not(gs.fBorder);
  848.             fRedraw = fTrue;
  849.             break;
  850.           case 'l':
  851.             not(gs.fLabel);
  852.             fRedraw = fTrue;
  853.             break;
  854.           case 'j':
  855.             not(gs.fJetTrail);
  856.             break;
  857.           case '<':
  858.             if (gs.nScale > 100) {
  859.               gs.nScale -= 100;
  860.               fResize = fTrue;
  861.             }
  862.             break;
  863.           case '>':
  864.             if (gs.nScale < 400) {
  865.               gs.nScale += 100;
  866.               fResize = fTrue;
  867.             }
  868.             break;
  869.           case '[':
  870.             if (gi.nMode == gGlobe && gs.rTilt > -rDegQuad) {
  871.               gs.rTilt = gs.rTilt > -rDegQuad ? gs.rTilt-11.25 : -rDegQuad;
  872.               fRedraw = fTrue;
  873.             }
  874.             break;
  875.           case ']':
  876.             if (gi.nMode == gGlobe && gs.rTilt < rDegQuad) {
  877.               gs.rTilt = gs.rTilt < rDegQuad ? gs.rTilt+11.25 : rDegQuad;
  878.               fRedraw = fTrue;
  879.             }
  880.             break;
  881.           case 'Q':
  882.             SquareX(&gs.xWin, &gs.yWin, fTrue);
  883.             fResize = fTrue;
  884.             break;
  885.           case 'R':
  886.             for (i = oChi; i <= oVes; i++)
  887.               not(ignore[i]);
  888.             for (i = oLil; i <= oEP; i++)
  889.               not(ignore[i]);
  890.             fCast = fTrue;
  891.             break;
  892.           case 'C':
  893.             not(us.fCusp);
  894.             for (i = cuspLo; i <= cuspHi; i++)
  895.               ignore[i] = !us.fCusp || !ignore[i];
  896.             fCast = fTrue;
  897.             break;
  898.           case 'u':
  899.             not(us.fUranian);
  900.             for (i = uranLo; i <= uranHi; i++)
  901.               ignore[i] = !us.fUranian || !ignore[i];
  902.             fCast = fTrue;
  903.             break;
  904.           case 'U':
  905.             us.nStar = !us.nStar;
  906.             for (i = starLo; i <= starHi; i++)
  907.               ignore[i] = !us.nStar || !ignore[i];
  908.             fCast = fTrue;
  909.             break;
  910.           case 'c':
  911.             if (!us.nRel) {
  912.               us.nRel = rcDual;
  913.               ciTwin = ciMain;
  914.             } else
  915.               us.nRel = 0;
  916.             fCast = fTrue;
  917.             break;
  918.           case 's':
  919.             not(us.fSiderial);
  920.             fCast = fTrue;
  921.             break;
  922.           case 'h':
  923.             us.objCenter = us.objCenter ? 0 : 1;
  924.             fCast = fTrue;
  925.             break;
  926.           case 'f':
  927.             not(us.fFlip);
  928.             fCast = fTrue;
  929.             break;
  930.           case 'g':
  931.             not(us.fDecan);
  932.             fCast = fTrue;
  933.             break;
  934.           case '+':
  935.             Animate(gs.nAnim, abs(dir));
  936.             fCast = fTrue;
  937.             break;
  938.           case '-':
  939.             Animate(gs.nAnim, -abs(dir));
  940.             fCast = fTrue;
  941.             break;
  942.           case 'o':
  943.             ciSave = ciMain;
  944.             break;
  945.           case 'O':
  946.             ciMain = ciSave;
  947.             fCast = fTrue;
  948.             break;
  949. #ifdef TIME
  950.           case 'n':
  951.             FInputData(szNowCore);
  952.             ciMain = ciCore;
  953.             fCast = fTrue;
  954.             break;
  955. #endif
  956.           case 'N':                     /* The continuous update animation. */
  957.             gs.nAnim = gs.nAnim ? 0 : -10;
  958.             break;
  959.  
  960.           /* These are the nine different "add time to chart" animations. */
  961.           case '!': gs.nAnim = -1; break;
  962.           case '@': gs.nAnim = -2; break;
  963.           case '#': gs.nAnim = -3; break;
  964.           case '$': gs.nAnim = -4; break;
  965.           case '%': gs.nAnim = -5; break;
  966.           case '^': gs.nAnim = -6; break;
  967.           case '&': gs.nAnim = -7; break;
  968.           case '*': gs.nAnim = -8; break;
  969.           case '(': gs.nAnim = -9; break;
  970.  
  971.           /* Should we go switch to a new chart type? */
  972.           case 'V': gi.nMode = gWheel;      fRedraw = fTrue; break;
  973.           case 'A': gi.nMode = gGrid;       fRedraw = fTrue; break;
  974.           case 'Z': gi.nMode = gHorizon;    fRedraw = fTrue; break;
  975.           case 'S': gi.nMode = gOrbit;      fRedraw = fTrue; break;
  976.           case 'J': gi.nMode = gDisposit;   fRedraw = fTrue; break;
  977.           case 'L': gi.nMode = gAstroGraph; fRedraw = fTrue; break;
  978.           case 'K': gi.nMode = gCalendar;   fRedraw = fTrue; break;
  979.           case 'E': gi.nMode = gEphemeris;  fRedraw = fTrue; break;
  980.           case 'W': gi.nMode = gWorldMap;   fRedraw = fTrue; break;
  981.           case 'G': gi.nMode = gGlobe;      fRedraw = fTrue; break;
  982.           case 'P': gi.nMode = gPolar;      fRedraw = fTrue; break;
  983. #ifdef BIORHYTHM
  984.           case 'Y':            /* Should we switch to biorhythm chart? */
  985.             if (!us.nRel)
  986.               ciTwin = ciMain;
  987.             us.nRel = rcBiorhythm;
  988.             gi.nMode = gBiorhythm;
  989.             fCast = fTrue;
  990.             break;
  991. #endif
  992. #ifdef CONSTEL
  993.           case 'F':
  994.             if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  995.               gi.nMode = gWorldMap;
  996.             not(gs.fConstel);
  997.             fRedraw = fTrue;
  998.             break;
  999. #endif
  1000.           case '0':
  1001.             not(us.fPrimeVert);
  1002.             not(us.fCalendarYear);
  1003.             not(us.nEphemYears);
  1004.             not(gs.fMollewide);
  1005.             gi.nMode = (gi.nMode == gWheel ? gHouse :
  1006.               (gi.nMode == gHouse ? gWheel : gi.nMode));
  1007.             fRedraw = fTrue;
  1008.             break;
  1009.           case 'v': case 'H': case '?':
  1010. #ifdef MSG
  1011.             _setvideomode(_DEFAULTMODE);
  1012.             if (key != 'v')
  1013.               _settextrows(50);
  1014. #endif
  1015. #ifdef BGI
  1016.             restorecrtmode();
  1017. #ifdef ATARI                        /* Ajout Abel PHILIPPE */
  1018.             Cur_on();
  1019. #else
  1020.             if (key != 'v')
  1021.               textmode(C4350);
  1022. #endif                                /* Ajout Abel PHILIPPE */
  1023. #endif
  1024.             length = us.nScrollRow;
  1025.             us.nScrollRow = 0;
  1026.             if (key == 'v')
  1027.               ChartListing();
  1028.             else
  1029.               DisplayKeysX();
  1030.             us.nScrollRow = length;
  1031. #ifdef PCG
  1032.             while (!kbhit())
  1033.               ;
  1034.             key = getch();
  1035.             if (key == 'q' || key == chEscape || key == chBreak) {
  1036.               fBreak = fTrue;
  1037.               break;
  1038.             }
  1039.             BeginX();
  1040.             fResize = fTrue;
  1041. #endif
  1042.             break;
  1043.           case chReturn:
  1044.             CommandLineX();
  1045.             fResize = fCast = fTrue;
  1046.             break;
  1047. #ifdef PCG
  1048.           case chTab:
  1049.             if (gi.nRes == gs.nResHi)
  1050.               gi.nRes = gs.nResLo;
  1051.             else
  1052.               gi.nRes = gs.nResHi;
  1053.             BeginX();
  1054.             gs.xWin = xPcScreen;
  1055.             gs.yWin = yPcScreen;
  1056.             SquareX(&gs.xWin, &gs.yWin, fFalse);
  1057.             fResize = fTrue;
  1058.             break;
  1059. #endif
  1060.           case chDelete:
  1061. #ifdef PCG
  1062. #ifdef MOUSE
  1063.             MouseShow(fFalse);
  1064. #endif
  1065. #endif /* PCG */
  1066.             fT = gs.fJetTrail;
  1067.             gs.fJetTrail = fFalse;
  1068.             DrawClearScreen();
  1069.             gs.fJetTrail = fT;
  1070.             break;
  1071. #ifdef MOUSE
  1072.           case 'z'-'`': coldrw = kBlack;   break;
  1073.           case 'e'-'`': coldrw = kMaroon;  break;
  1074.           case 'f'-'`': coldrw = kDkGreen; break;
  1075.           case 'o'-'`': coldrw = kOrange;  break;
  1076.           case 'n'-'`': coldrw = kDkBlue;  break;
  1077.           case 'u'-'`': coldrw = kPurple;  break;
  1078.           case 'k'-'`': coldrw = kDkCyan;  break;
  1079.           case 'l'-'`': coldrw = kLtGray;  break;
  1080.           case 'd'-'`': coldrw = kDkGray;  break;
  1081.           case 'r'-'`': coldrw = kRed;     break;
  1082.           case 'g'-'`': coldrw = kGreen;   break;
  1083.           case 'y'-'`': coldrw = kYellow;  break;
  1084.           case 'b'-'`': coldrw = kBlue;    break;
  1085.           case 'v'-'`': coldrw = kMagenta; break;
  1086.           case 'j'-'`': coldrw = kCyan;    break;
  1087.           case 'a'-'`': coldrw = kWhite;   break;
  1088. #ifdef PCG
  1089.           case 't'-'`':
  1090.             MouseShow(fFalse);
  1091.             if (buttonx >= 0)
  1092. #ifdef MSG
  1093.               _rectangle(_GBORDER, buttonx, buttony, mousex, mousey);
  1094. #else
  1095.               DrawEdge(Min(buttonx, mousex) - gi.xOffset,
  1096.                 Min(buttony, mousey) - gi.yOffset,
  1097.                 Max(mousex, buttonx) - gi.xOffset,
  1098.                 Max(mousey, buttony) - gi.yOffset);
  1099. #endif
  1100.             MouseShow(fTrue);
  1101.             break;
  1102.           case 'x'-'`':
  1103.             MouseShow(fFalse);
  1104.             if (buttonx >= 0)
  1105. #ifdef MSG
  1106.               _ellipse(_GBORDER, buttonx, buttony, mousex, mousey);
  1107. #else
  1108.               DrawEllipse(Min(buttonx, mousex) - gi.xOffset,
  1109.                 Min(buttony, mousey) - gi.yOffset,
  1110.                 Max(mousex, buttonx) - gi.xOffset,
  1111.                 Max(mousey, buttony) - gi.yOffset);
  1112. #endif
  1113.             MouseShow(fTrue);
  1114.             break;
  1115. #endif /* PCG */
  1116. #endif /* MOUSE */
  1117.           case 'q': case chEscape: case chBreak:
  1118.             fBreak = fTrue;
  1119.             break;
  1120.           default:
  1121.             if (key > '0' && key <= '9') {
  1122. #ifdef PCG
  1123.               if (gs.nAnim && !fPause)
  1124. #endif
  1125.                 /* Process numbers 1..9 signifying animation rate. */
  1126.                 dir = (dir > 0 ? 1 : -1)*(key-'0');
  1127. #ifdef PCG
  1128.               else {
  1129.                 /* If we aren't in animation mode, then 1..9 refers to the */
  1130.                 /* clipping "quadrant" to use if chart size > screen size. */
  1131.                 xcorner = key-'0';
  1132.                 fResize = fTrue;
  1133.               }
  1134. #endif
  1135.               break;
  1136.             } else if (FBetween(key, 201, 248)) {
  1137.               is.fSzInteract = fTrue;
  1138.               if (szMacro[key-201]) {
  1139.                 FProcessCommandLine(szMacro[key-201]);
  1140.                 fResize = fCast = fTrue;
  1141.               }
  1142.               is.fSzInteract = fFalse;
  1143.               break;
  1144.             }
  1145.             putchar(chBell);    /* Any key not bound will sound a beep. */
  1146.           }  /* switch */
  1147.         }  /* if */
  1148. #ifdef X11
  1149.       default:
  1150.         ;
  1151.       }  /* switch */
  1152.     }  /* if */
  1153. #endif
  1154.   }  /* while */
  1155. }
  1156.  
  1157.  
  1158. /* This is called right before program termination to get rid of the window. */
  1159.  
  1160. void EndX()
  1161. {
  1162. #ifdef X11
  1163.   XFreeGC(gi.disp, gi.gc);
  1164.   XFreeGC(gi.disp, gi.pmgc);
  1165.   XFreePixmap(gi.disp, gi.pmap);
  1166.   XDestroyWindow(gi.disp, gi.wind);
  1167.   XCloseDisplay(gi.disp);
  1168. #endif
  1169. #ifdef MSG
  1170.   _setvideomode(_DEFAULTMODE);
  1171. #endif
  1172. #ifdef BGI
  1173.   restorecrtmode();
  1174. #ifdef ATARI                        /* Ajout Abel PHILIPPE */
  1175.   Cur_on();
  1176. #endif
  1177. #endif
  1178. }
  1179. #endif /* ISG */
  1180.  
  1181.  
  1182. /*
  1183. ******************************************************************************
  1184. ** Main Graphics Processing.
  1185. ******************************************************************************
  1186. */
  1187.  
  1188. /* Process one command line switch passed to the program dealing with the    */
  1189. /* graphics features. This is just like the processing of each switch in the */
  1190. /* main program, however here each switch has been prefixed with an 'X'.     */
  1191.  
  1192. int NProcessSwitchesX(argc, argv, pos, fOr, fAnd, fNot)
  1193. int argc, pos;
  1194. bool fOr, fAnd, fNot;
  1195. char **argv;
  1196. {
  1197.   int darg = 0, i, j;
  1198.   real rT;
  1199.   char ch1;
  1200.  
  1201.   ch1 = argv[0][pos+1];
  1202.   switch (argv[0][pos]) {
  1203.   case chNull:
  1204.     break;
  1205.  
  1206.   case 'b':
  1207.     if (is.fSzInteract) {
  1208.       ErrorArgv("Xb");
  1209.       return tcError;
  1210.     }
  1211.     ch1 = ChCap(ch1);
  1212.     if (FValidBmpmode(ch1))
  1213.       gs.chBmpMode = ch1;
  1214.     SwitchF2(gs.fBitmap);
  1215.     gs.fPS = gs.fMeta = fFalse;
  1216.     break;
  1217.  
  1218. #ifdef PS
  1219.   case 'p':
  1220.     if (is.fSzInteract) {
  1221.       ErrorArgv("Xp");
  1222.       return tcError;
  1223.     }
  1224.     gs.fPS = fTrue + (ch1 != '0');
  1225.     gs.fBitmap = gs.fMeta = fFalse;
  1226.     break;
  1227. #endif
  1228.  
  1229. #ifdef META
  1230.   case 'M':
  1231.     if (is.fSzInteract) {
  1232.       ErrorArgv("XM");
  1233.       return tcError;
  1234.     }
  1235.     if (ch1 == '0')
  1236.       SwitchF(gs.fFont);
  1237.     SwitchF2(gs.fMeta);
  1238.     gs.fBitmap = gs.fPS = fFalse;
  1239.     break;
  1240. #endif
  1241.  
  1242.   case 'o':
  1243.     if (is.fSzInteract) {
  1244.       ErrorArgv("Xo");
  1245.       return tcError;
  1246.     }
  1247.     if (argc <= 1) {
  1248.       ErrorArgc("Xo");
  1249.       return tcError;
  1250.     }
  1251.     if (!gs.fBitmap && !gs.fPS && !gs.fMeta)
  1252.       gs.fBitmap = fTrue;
  1253.     gi.szFileOut = SzPersist(argv[1]);
  1254.     darg++;
  1255.     break;
  1256.  
  1257. #ifdef X11
  1258.   case 'B':
  1259.     if (is.fSzInteract) {
  1260.       ErrorArgv("XB");
  1261.       return tcError;
  1262.     }
  1263.     SwitchF(gs.fRoot);
  1264.     break;
  1265. #endif
  1266.  
  1267.   case 'm':
  1268.     SwitchF(gs.fColor);
  1269.     break;
  1270.  
  1271.   case 'r':
  1272.     SwitchF(gs.fInverse);
  1273.     break;
  1274.  
  1275.   case 'w':
  1276.     if (argc <= 1) {
  1277.       ErrorArgc("Xw");
  1278.       return tcError;
  1279.     }
  1280.     i = atoi(argv[1]);
  1281.     if (argc > 2 && ((j = atoi(argv[2])) || argv[2][0] == '0')) {
  1282.       argc--; argv++;
  1283.       darg++;
  1284.     } else
  1285.       j = i;
  1286.     if (!FValidGraphx(i)) {
  1287.       ErrorValN("Xw", i);
  1288.       return tcError;
  1289.     }
  1290.     if (!FValidGraphy(j)) {
  1291.       ErrorValN("Xw", j);
  1292.       return tcError;
  1293.     }
  1294.     gs.xWin = i; gs.yWin = j;
  1295.     darg++;
  1296.     break;
  1297.  
  1298.   case 's':
  1299.     if (argc <= 1) {
  1300.       ErrorArgc("Xs");
  1301.       return tcError;
  1302.     }
  1303.     i = atoi(argv[1]);
  1304.     if (i < 100)
  1305.       i *= 100;
  1306.     if (!FValidScale(i)) {
  1307.       ErrorValN("Xs", i);
  1308.       return tcError;
  1309.     }
  1310.     gs.nScale = i;
  1311.     darg++;
  1312.     break;
  1313.  
  1314.   case 'i':
  1315.     SwitchF(gs.fAlt);
  1316.     break;
  1317.  
  1318.   case 't':
  1319.     SwitchF(gs.fText);
  1320.     break;
  1321.  
  1322.   case 'u':
  1323.     SwitchF(gs.fBorder);
  1324.     break;
  1325.  
  1326.   case 'l':
  1327.     SwitchF(gs.fLabel);
  1328.     break;
  1329.  
  1330.   case 'j':
  1331.     SwitchF(gs.fJetTrail);
  1332.     break;
  1333.  
  1334.   case '1':
  1335.     if (argc <= 1) {
  1336.       ErrorArgc("X1");
  1337.       return tcError;
  1338.     }
  1339.     i = atoi(argv[1]);
  1340.     if (!FItem(i)) {
  1341.       ErrorValN("X1", i);
  1342.       return tcError;
  1343.     }
  1344.     gs.nLeft = i;
  1345.     darg++;
  1346.     break;
  1347.  
  1348.   case '2':
  1349.     if (argc <= 1) {
  1350.       ErrorArgc("X2");
  1351.       return tcError;
  1352.     }
  1353.     i = atoi(argv[1]);
  1354.     if (!FItem(i)) {
  1355.       ErrorValN("X2", i);
  1356.       return tcError;
  1357.     }
  1358.     gs.nLeft = -i;
  1359.     darg++;
  1360.     break;
  1361.  
  1362.   case 'd':
  1363.     if (is.fSzInteract) {
  1364.       ErrorArgv("Xd");
  1365.       return tcError;
  1366.     }
  1367.     if (argc <= 1) {
  1368.       ErrorArgc("Xd");
  1369.       return tcError;
  1370.     }
  1371.     gs.szDisplay = SzPersist(argv[1]);
  1372.     darg++;
  1373.     break;
  1374.  
  1375.   case 'W':
  1376.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1377.       darg++;
  1378.       if (!FValidRotation(i)) {
  1379.         ErrorValN("XW", i);
  1380.         return tcError;
  1381.       }
  1382.       gs.nRot = i;
  1383.     }
  1384.     gi.nMode = gWorldMap;
  1385.     if (ch1 == '0')
  1386.       gs.fMollewide = fTrue;
  1387.     is.fHaveInfo = fTrue;
  1388.     break;
  1389.  
  1390.   case 'G':
  1391.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1392.       darg++;
  1393.       if (!FValidRotation(i)) {
  1394.         ErrorValN("XG", i);
  1395.         return tcError;
  1396.       }
  1397.       gs.nRot = i;
  1398.       if (argc > 2 && ((rT = atof(argv[2])) || argv[2][0] == '0')) {
  1399.         darg++;
  1400.         if (!FValidTilt(rT)) {
  1401.           ErrorValR("XG", rT);
  1402.           return tcError;
  1403.         }
  1404.         gs.rTilt = rT;
  1405.       }
  1406.     }
  1407.     gi.nMode = gGlobe;
  1408.     is.fHaveInfo = fTrue;
  1409.     break;
  1410.  
  1411.   case 'P':
  1412.     if (argc > 1 && ((i = atoi(argv[1])) || argv[1][0] == '0')) {
  1413.       darg++;
  1414.       if (!FValidRotation(i)) {
  1415.         ErrorValN("XP", i);
  1416.         return tcError;
  1417.       }
  1418.     } else
  1419.       i = 0;
  1420.     gs.nRot = i;
  1421.     gi.nMode = gPolar;
  1422.     if (ch1 == '0')
  1423.       gs.fPrintMap = fTrue;
  1424.     is.fHaveInfo = fTrue;
  1425.     break;
  1426.  
  1427. #ifdef CONSTEL
  1428.   case 'F':
  1429.     if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  1430.       gi.nMode = gWorldMap;
  1431.     not(gs.fConstel);
  1432.     is.fHaveInfo = fTrue;
  1433.     break;
  1434. #endif
  1435.  
  1436. #ifdef ISG
  1437.   case 'n':
  1438.     if (argc > 1 && (i = atoi(argv[1])))
  1439.       darg++;
  1440.     else
  1441.       i = 10;
  1442.     if (i < 1 || i > 10) {
  1443.       ErrorValN("Xn", i);
  1444.       return tcError;
  1445.     }
  1446.     gs.nAnim = i;
  1447.     break;
  1448. #endif
  1449.  
  1450.   default:
  1451.     ErrorSwitch(argv[0]);
  1452.     return tcError;
  1453.   }
  1454.   /* 'darg' contains the value to be added to argc when we return. */
  1455.   return darg;
  1456. }
  1457.  
  1458.  
  1459. /* Process one command line switch passed to the program dealing with more  */
  1460. /* obscure graphics options. This is structured very much like the function */
  1461. /* NProcessSwitchesX(), except here we know each switch begins with 'YX'.   */
  1462.  
  1463. int NProcessSwitchesRareX(argc, argv, pos)
  1464. int argc, pos;
  1465. char **argv;
  1466. {
  1467.   int darg = 0, i, j;
  1468.   char ch1;
  1469.  
  1470.   ch1 = argv[0][pos+1];
  1471.   switch (argv[0][pos]) {
  1472.   case chNull:
  1473.     if (argc <= 2) {
  1474.       ErrorArgc("YX");
  1475.       return tcError;
  1476.     }
  1477. #ifdef PCG
  1478.     i = atoi(argv[1]);
  1479.     if (!FValidResmode(i)) {
  1480.       ErrorValN("YX", i);
  1481.       return tcError;
  1482.     }
  1483.     gs.nResHi = i;
  1484.     i = atoi(argv[2]);
  1485.     if (!FValidResmode(i)) {
  1486.       ErrorValN("YX", i);
  1487.       return tcError;
  1488.     }
  1489.     gs.nResLo = i;
  1490.     gs.fBitmap = gs.fPS = gs.fMeta = fFalse;
  1491. #endif
  1492.     darg += 2;
  1493.     break;
  1494.  
  1495.   case 'G':
  1496.     if (argc <= 1) {
  1497.       ErrorArgc("YXG");
  1498.       return tcError;
  1499.     }
  1500.     i = atoi(argv[1]);
  1501.     if (!FValidGlyphs(i)) {
  1502.       ErrorValN("YXg", i);
  1503.       return tcError;
  1504.     }
  1505.     gs.nGlyphs = i;
  1506.     j = i/1000;
  1507.     if (FBetween(j, 1, 2))
  1508.       szDrawSign[sCap] = szDrawSign[cSign+j];
  1509.     j = (i/100)%10;
  1510.     if (FBetween(j, 1, 2))
  1511.       szDrawObject[oUra] = szDrawObject[oNorm+j];
  1512.     j = (i/10)%10;
  1513.     if (FBetween(j, 1, 2))
  1514.       szDrawObject[oPlu] = szDrawObject[oNorm+2+j];
  1515.     j = i%10;
  1516.     if (FBetween(j, 1, 3))
  1517.       szDrawObject[oLil] = szDrawObject[oNorm+4+j];
  1518.     darg++;
  1519.     break;
  1520.  
  1521.   case 'g':
  1522.     if (argc <= 1) {
  1523.       ErrorArgc("YXg");
  1524.       return tcError;
  1525.     }
  1526.     i = atoi(argv[1]);
  1527.     if (!FValidGrid(i)) {
  1528.       ErrorValN("YXg", i);
  1529.       return tcError;
  1530.     }
  1531.     gs.nGridCell = i;
  1532.     darg++;
  1533.     break;
  1534.  
  1535.   case 'f':
  1536.     if (argc <= 1) {
  1537.       ErrorArgc("YXf");
  1538.       return tcError;
  1539.     }
  1540.     gs.fFont = atoi(argv[1]);
  1541.     darg++;
  1542.     break;
  1543.  
  1544. #ifdef PS
  1545.   case 'p':
  1546.     if (ch1 == '0') {
  1547.       if (argc <= 2) {
  1548.         ErrorArgc("YXp0");
  1549.         return tcError;
  1550.       }
  1551.       gs.xInch = atof(argv[1]);
  1552.       gs.yInch = atof(argv[2]);
  1553.       darg += 2;
  1554.       break;
  1555.     }
  1556.     if (argc <= 1) {
  1557.       ErrorArgc("YXp");
  1558.       return tcError;
  1559.     }
  1560.     gs.nOrient = atoi(argv[1]);
  1561.     darg++;
  1562.     break;
  1563. #endif
  1564.  
  1565.   default:
  1566.     ErrorSwitch(argv[0]);
  1567.     return tcError;
  1568.   }
  1569.   /* 'darg' contains the value to be added to argc when we return. */
  1570.   return darg;
  1571. }
  1572.  
  1573.  
  1574. /* This is the main interface to all the graphics features. This routine     */
  1575. /* is called from the main program if any of the -X switches were specified, */
  1576. /* and it sets up for and goes and generates the appropriate graphics chart. */
  1577. /* We return fTrue if successfull, fFalse if some non-fatal error occurred.  */
  1578.  
  1579. bool FActionX()
  1580. {
  1581.   int i;
  1582.  
  1583.   /* Set up variables in preparation for graphics. Set the glyphs for     */
  1584.   /* certain objects to point to their current setting, and if doing      */
  1585.   /* constellations, give a couple stars more correct astronomical names. */
  1586.  
  1587. #ifdef CONSTEL
  1588.   if (gs.fConstel) {
  1589.     szObjName[starLo-1+10] = "Alnilam";  /* Normally "Orion"     */
  1590.     szObjName[starLo-1+47] = "M31";      /* Normally "Andromeda" */
  1591.   }
  1592. #endif
  1593.   i = gs.nGlyphs/1000;
  1594.   szDrawSign[sCap] = szDrawSign[cSign+(i == 2 ? 2 : 1)];
  1595.   i = (gs.nGlyphs/100)%10;
  1596.   szDrawObject[oUra] = szDrawObject[oNorm+(i == 2 ? 2 : 1)];
  1597.   i = (gs.nGlyphs/10)%10;
  1598.   szDrawObject[oPlu] = szDrawObject[oNorm+2+(i == 2 ? 2 : 1)];
  1599.   i = gs.nGlyphs%10;
  1600.   szDrawObject[oLil] =
  1601.     szDrawObject[oNorm+4+(FBetween(i, 2, 3) ? i : fSouthNode ? 3 : 1)];
  1602. /*  if (fSouthNode)
  1603.     szObjectFont[oSou] = '>';*/
  1604.   gi.fFile = (gs.fBitmap || gs.fPS || gs.fMeta);
  1605. #ifdef PS
  1606.   gi.fEps = gs.fPS > fTrue;
  1607. #endif
  1608.  
  1609.   /* First figure out what graphic mode to generate the chart in, based on */
  1610.   /* various non-X command switches, e.g. -L combined with -X, -g combined */
  1611.   /* with -X, and so on, and determine the size the window is to be, too.  */
  1612.  
  1613.   if (gi.nMode == gWheel) {
  1614.     if (us.fWheel)
  1615.       gi.nMode = gHouse;
  1616.     else if (us.fGrid || us.fMidpoint) {
  1617.       gi.nMode = gGrid;
  1618.       if (us.nRel <= rcDual && us.fMidpoint && !us.fAspList)
  1619.         us.fGridConfig = fTrue;
  1620.       gs.xWin = gs.yWin =
  1621.         (gs.nGridCell + (us.nRel <= rcDual))*CELLSIZE*gi.nScale + 1;
  1622.     } else if (us.fHorizon)
  1623.       gi.nMode = gHorizon;
  1624.     else if (us.fOrbit)
  1625.       gi.nMode = gOrbit;
  1626.     else if (us.fInfluence)
  1627.       gi.nMode = gDisposit;
  1628.     else if (us.fAstroGraph)
  1629.       gi.nMode = gAstroGraph;
  1630.     else if (us.fCalendar)
  1631.       gi.nMode = gCalendar;
  1632.     else if (us.fEphemeris)
  1633.       gi.nMode = gEphemeris;
  1634.     else if (us.nRel == rcBiorhythm)
  1635.       gi.nMode = gBiorhythm;
  1636.   }
  1637.   if (fMap) {
  1638.     gs.xWin = nDegMax*gi.nScale;
  1639.     gs.yWin = nDegHalf*gi.nScale;
  1640.   }
  1641.   gi.nScaleT = gs.fPS ? PSMUL : (gs.fMeta ? METAMUL : 1);
  1642.  
  1643.   if (gi.fFile) {
  1644.     if (gs.xWin == 0)
  1645.       gs.xWin = DEFAULTX;
  1646.     if (gs.yWin == 0)
  1647.       gs.yWin = DEFAULTY;
  1648.     if (fSidebar)
  1649.       gs.xWin += SIDESIZE;
  1650.     if (gs.xWin > BITMAPX)
  1651.       gs.xWin = BITMAPX;
  1652.     if (gs.yWin > BITMAPY)
  1653.       gs.yWin = BITMAPY;
  1654.     BeginFileX();
  1655.     if (gs.fBitmap) {
  1656.       gi.cbBmpRow = (gs.xWin + 1) >> 1;
  1657.       gi.yBand = gs.yWin;
  1658.       if (!FEnsureGrid())
  1659.         return fFalse;
  1660.       while ((gi.bm = PAllocate((long)gi.cbBmpRow * gi.yBand, fTrue, NULL)) ==
  1661.         NULL) {
  1662.         PrintWarning("The bitmap must be generated in multiple stages.");
  1663.         gi.yBand = (gi.yBand + 1) / 2;
  1664.         if (gi.yBand < 1 || gs.chBmpMode != 'B')
  1665.           return fFalse;
  1666.       }
  1667.       if (gi.yBand == gs.yWin)
  1668.         gi.yBand = 0;
  1669.       else {
  1670.         gi.yOffset = gs.yWin - gs.yWin % gi.yBand;
  1671.         if (gi.yOffset == gs.yWin)
  1672.           gi.yOffset -= gi.yBand;
  1673.       }
  1674.     }
  1675. #ifdef PS
  1676.     else if (gs.fPS)
  1677.       PsBegin();
  1678. #endif
  1679. #ifdef META
  1680.     else {
  1681.       if (!FEnsureGrid())
  1682.         return fFalse;
  1683.       for (gi.cbMeta = MAXMETA; gi.cbMeta > 0 &&
  1684.         (gi.bm = PAllocate(gi.cbMeta, fTrue, NULL)) == NULL;
  1685.         gi.cbMeta -= MAXMETA/8)
  1686.         PrintWarning("Attempting to get maximum memory for metafile.");
  1687.       if (gi.cbMeta == 0)
  1688.         return fFalse;
  1689.       gs.xWin   *= METAMUL;  /* Increase chart sizes and scales behind the */
  1690.       gs.yWin   *= METAMUL;  /* scenes to make graphics look smoother.     */
  1691.       gs.nScale *= METAMUL;
  1692.     }
  1693. #endif
  1694.     InitColorsX();
  1695.   }
  1696. #ifdef ISG
  1697.   else {
  1698. #ifdef PCG
  1699.     BeginX();
  1700.     if (gs.xWin == 0 || gs.yWin == 0) {
  1701.       if (gs.xWin == 0)
  1702.         gs.xWin = xPcScreen;
  1703.       if (gs.yWin == 0)
  1704.         gs.yWin = yPcScreen;
  1705.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  1706.     } else if (fSidebar)
  1707.       gs.xWin += SIDESIZE;
  1708. #else
  1709.     if (gs.xWin == 0 || gs.yWin == 0) {
  1710.       if (gs.xWin == 0)
  1711.         gs.xWin = DEFAULTX;
  1712.       if (gs.yWin == 0)
  1713.         gs.yWin = DEFAULTY;
  1714.       SquareX(&gs.xWin, &gs.yWin, fFalse);
  1715.     } else if (fSidebar)
  1716.       gs.xWin += SIDESIZE;
  1717.     BeginX();
  1718. #endif
  1719.   }
  1720. #endif /* ISG */
  1721.  
  1722.   if (gi.fFile || gs.fRoot)    /* Go draw the graphic chart. */
  1723.     DrawChartX();
  1724.   if (gi.fFile) {    /* Write bitmap to file if in that mode. */
  1725.     EndFileX();
  1726.     while (gi.yBand) {
  1727.       gi.yOffset -= gi.yBand;
  1728.       DrawChartX();
  1729.       EndFileX();
  1730.     }
  1731.     if (!gs.fPS)
  1732.       DeallocateHuge(gi.bm);
  1733.   }
  1734. #ifdef ISG
  1735.   else {
  1736. #ifdef X11
  1737.     if (gs.fRoot) {                                         /* Process -XB. */
  1738.       XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  1739.       XClearWindow(gi.disp, gi.root);
  1740.  
  1741.       /* If -Xn in effect with -XB, then enter infinite loop where we */
  1742.       /* calculate and animate chart, displaying on the root window.  */
  1743.       while (gs.nAnim) {
  1744.         Animate(gs.nAnim, 1);
  1745.         if (!gs.fJetTrail)
  1746.           XFillRectangle(gi.disp, gi.pmap, gi.pmgc, 0, 0, gs.xWin, gs.yWin);
  1747.         DrawChartX();
  1748.         XSetWindowBackgroundPixmap(gi.disp, gi.root, gi.pmap);
  1749.         XClearWindow(gi.disp, gi.root);
  1750.       }
  1751.     } else
  1752. #endif
  1753.       InteractX();    /* Window's up; process commands given to window now. */
  1754.     EndX();
  1755.   }
  1756. #endif /* ISG */
  1757.   return fTrue;
  1758. }
  1759. #endif /* GRAPH */
  1760.  
  1761. /* xscreen.c */
  1762.